package com.chiyoyo.rabbitmq.framework.service;

import com.chiyoyo.rabbitmq.framework.annotation.RabbitMq;
import com.chiyoyo.rabbitmq.framework.dto.InitRabbitBinding;
import org.springframework.amqp.core.AbstractExchange;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;

/**
 * @author chil
 * 抽象消息队列服务类
 * 提供了消息队列服务的基本结构和方法的抽象定义，子类需要实现具体的交换机和绑定初始化逻辑。
 */
public abstract class AbstractMQService {

    public static String SERVICE_NAME = "MQService";

    /**
     * 初始化绑定关系的方法
     * 根据传入的参数创建队列、交换机和绑定关系
     *
     * @param rabbitMq          消息队列的配置对象
     * @param queueName         队列名称
     * @param admin             RabbitMQ管理对象，用于声明队列、交换机和绑定
     * @param connectionFactory RabbitMQ连接工厂对象，用于获取队列信息
     * @param isInitDlxMap      是否初始化死信队列映射
     * @param isAddDlxPrefix    是否为死信队列添加前缀
     * @return 返回创建的队列对象
     */
    public Queue initBinding(RabbitMq rabbitMq, String queueName, RabbitAdmin admin, CachingConnectionFactory connectionFactory, boolean isInitDlxMap, boolean isAddDlxPrefix) {
        String originalVirtualHost = connectionFactory.getVirtualHost();
        if (!"".equals(rabbitMq.virtualHost())) {
            connectionFactory.setVirtualHost(rabbitMq.virtualHost());
        }
        InitRabbitBinding initRabbitBinding = new InitRabbitBinding(rabbitMq, queueName, isInitDlxMap, isAddDlxPrefix);
        // 初始化队列
        Queue queue = new Queue(initRabbitBinding.getQueue(), rabbitMq.isPersistence(), false, false, initRabbitBinding.getArgs());
        // 绑定队列
        admin.declareQueue(queue);
        // 绑定交换机
        AbstractExchange exchange = initExchange(initRabbitBinding.getExchange(), rabbitMq);
        admin.declareExchange(exchange);
        // 绑定
        admin.declareBinding(this.initBinding(queue, exchange, initRabbitBinding.getRoutingKey(), rabbitMq));
        if (!"".equals(rabbitMq.virtualHost())) {
            // 恢复配置文件虚拟主机
            connectionFactory.setVirtualHost(originalVirtualHost);
        }
        return queue;
    }

    /**
     * 初始化交换机
     * 子类需要实现此方法，根据给定的交换机名称和配置创建具体的交换机实例
     *
     * @param exchange 交换机名称
     * @param rabbitMq 消息队列配置对象
     * @return 返回创建的交换机实例
     */
    protected abstract AbstractExchange initExchange(String exchange, RabbitMq rabbitMq);

    /**
     * 初始化绑定关系
     * 子类需要实现此方法，创建绑定对象，用于将队列与交换机绑定
     *
     * @param queue      队列对象
     * @param exchange   交换机对象
     * @param routingKey 路由键
     * @param rabbitMq   消息队列配置对象
     * @return 返回创建的绑定对象
     */
    protected abstract Binding initBinding(Queue queue, AbstractExchange exchange, String routingKey, RabbitMq rabbitMq);
}
